package ru.amse.tsyganov.jumleditor.graphicaleditor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;

import ru.amse.tsyganov.jumleditor.commands.Command;
import ru.amse.tsyganov.jumleditor.commands.CommandFactory;
import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.model.Transition;
import ru.amse.tsyganov.jumleditor.view.Cursors;
import ru.amse.tsyganov.jumleditor.view.Line;
import ru.amse.tsyganov.jumleditor.view.StateView;
import ru.amse.tsyganov.jumleditor.view.TransitionDraughtsman;
import ru.amse.tsyganov.jumleditor.view.TransitionView;

/*package*/ class AddTransitionMode extends EditorMode {

	private final GraphicalEditor graphicalEditor;
	
	private StateView<? extends State> sourceState;
	
	private StateView<? extends State> targetState;
	
	private int currentX;
	
	private int currentY;
	
	public AddTransitionMode(GraphicalEditor graphicalEditor) {	
		this.graphicalEditor = graphicalEditor;	
	}
	
	@Override
	public void initState() {
		graphicalEditor.getCanvas().setCursor(
				Cursors.getCursorNo());
		
		sourceState = null;
		targetState = null;
	}
	
	@Override
	public void mouseDoubleClick(MouseEvent e) {
	}

	@Override
	public void mouseDown(MouseEvent e) {
		sourceState = graphicalEditor.
			getActivityGraphView().getStateView(e.x, e.y);
		
		targetState = null;
	}

	@Override
	public void mouseMove(MouseEvent e) {
		currentX = e.x;
		currentY = e.y;
		
		targetState = graphicalEditor.
			getActivityGraphView().getStateView(e.x, e.y);
		
		if (targetState != null) {
			graphicalEditor.getCanvas().setCursor(
					Cursors.getCursorArrowPlus());
		} else {
			graphicalEditor.getCanvas().setCursor(
					Cursors.getCursorNo());
		}
	}

	@Override
	public void mouseUp(MouseEvent e) {
		if (targetState != null) {
			assert sourceState != null;
			
			boolean duplicate = false;
			for (Transition t : sourceState.getModel().
					getStateVertex().getOutgoing()) {
				
				if (t.getTarget() == targetState.
						getModel().getStateVertex()) {
					
					duplicate = true;
					break;
				}
			}
			if (!duplicate && sourceState != targetState) {
				Transition transition = new Transition(
						sourceState.getModel().getStateVertex(), 
						targetState.getModel().getStateVertex());
				
				TransitionView<Transition> transitionView = 
					new TransitionView<Transition>(transition, 
							graphicalEditor.getActivityGraphView());
			
				Command newTransitionCommand = 
					CommandFactory.createNewTransitionCommand(
							transitionView);
									
				graphicalEditor.getViewsManager().executeCommand(
						newTransitionCommand);
			}
			graphicalEditor.setEditorMode(graphicalEditor.getSelectionMode());
		}
		
		sourceState = null;
		targetState = null;
	}

	@Override
	public void paintControl(PaintEvent e) {
		if (sourceState != null) {
			if (sourceState.getRectangle().
					contains(currentX, currentY)) {
				
				return;
			}
			
			GC gc = e.gc;
			
			if (targetState != null) {
				Rectangle rect1 = sourceState.getRectangle();
				Rectangle rect2 = targetState.getRectangle();
				
				Point centerPointOfFirstRect = 
					new Point(rect1.x + rect1.width / 2,
							rect1.y + rect1.height / 2);
				
				Point centerPointOfSecondRect = 
					new Point(rect2.x + rect2.width / 2,
							rect2.y + rect2.height / 2);
				
				Point connectionPoint1 = 
					targetState.getConnectionPoint(centerPointOfFirstRect, true);
				
				Point connectionPoint2 = 
					sourceState.getConnectionPoint(centerPointOfSecondRect, false);
				
				Line line = new Line(connectionPoint1.x, connectionPoint1.y, 
				connectionPoint2.x, connectionPoint2.y);
				
				TransitionDraughtsman.drawArrowedLine(gc, line, false);
			} else {
				Point p = new Point(currentX, currentY);
				Point connectionPoint = 
					sourceState.getConnectionPoint(p, false);
				
				Line line = new Line(p.x, p.y, 
						connectionPoint.x, connectionPoint.y);
				TransitionDraughtsman.drawArrowedLine(gc, line, false);
				sourceState.paint(gc);
			}
			gc.setLineStyle(SWT.LINE_SOLID);
		} 
	}

	@Override
	public void keyPressed(KeyEvent e) {	
	}

	@Override
	public void keyReleased(KeyEvent e) {
	}
}
